// ==UserScript==
// @name         UEditor WORD文档上传工具
// @namespace    http://ms.zjer.cn/
// @version      4.0
// @description  为UEditor编辑器添加WORD文档上传功能，支持解析DOCX内容
// @author       zjlester
// @match        https://ms.zjer.cn/*
// @require      https://unpkg.com/mammoth@1.4.17/mammoth.browser.min.js
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// @grant        GM_setValue
// @grant        GM_getValue
// @connect      unpkg.com
// @connect      ms.zjer.cn
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

      // 创建全局变量存储参数
    window.ukey = null;
    window.is_admin = null;
    window.csrftk = null;

    // 存储所有拦截到的参数
    window.interceptedParams = {};

    // 定义要侦听的URL路径数组
    window.monitoredUrls = [
        'studio/manage/notice/add',
        'studio/manage/news/add',
        'studio/post/add',
        'studio/admin/creataffiche',
        'studio/admin/addnewsinfo'
    ];

    // 保存原始XMLHttpRequest
    const originalOpen = XMLHttpRequest.prototype.open;
    const originalSend = XMLHttpRequest.prototype.send;

    // 重写XMLHttpRequest的open方法
    XMLHttpRequest.prototype.open = function() {
        const method = arguments[0];
        const url = arguments[1];

        // 检查是否为目标URL（参数提取）
        if (url && url.includes('common/ueditor/index/index')) {
            console.log('拦截到目标请求:', url);

            // 解析URL参数
            const urlObj = new URL(url, window.location.origin);
            const params = Object.fromEntries(urlObj.searchParams.entries());

            // 存储所有参数
            window.interceptedParams = params;

            // 赋值给全局变量
            window.ukey = params.ukey || null;
            window.is_admin = params.is_admin || null;
            window.csrftk = params.csrftk || null;

            // 在控制台输出参数
            console.log('提取的参数:');
            console.table(params);

            // 输出全局变量状态
            console.log('全局变量已创建:');
            console.log(`ukey: ${window.ukey}`);
            console.log(`is_admin: ${window.is_admin}`);
            console.log(`csrftk: ${window.csrftk}`);

            // 添加自定义事件，方便其他脚本使用
            const event = new CustomEvent('ParamsIntercepted', { detail: params });
            document.dispatchEvent(event);
        }

        // 检查是否为需要侦听的URL
        if (url && window.monitoredUrls.some(monitoredUrl => url.includes(monitoredUrl))) {
            console.log(`侦听到目标URL: ${url}`);
            console.log(`匹配的路径: ${window.monitoredUrls.find(monitoredUrl => url.includes(monitoredUrl))}`);

            // 这里可以添加修改页面内容的代码
            // 目前先用log示例
            console.log('检测到目标页面，可以在这里修改页面内容');

            // 添加自定义事件，通知其他脚本
            const event = new CustomEvent('MonitoredUrlDetected', {
                detail: {
                    url: url,
                    matchedPath: window.monitoredUrls.find(monitoredUrl => url.includes(monitoredUrl))
                }
            });
            document.dispatchEvent(event);
        }

        // 调用原始open方法
        return originalOpen.apply(this, arguments);
    };

    // 重写send方法以保持一致性
    XMLHttpRequest.prototype.send = function() {
        return originalSend.apply(this, arguments);
    };

    // 监听页面URL变化（对于单页应用）
    let lastUrl = location.href;
    new MutationObserver(() => {
        const url = location.href;
        if (url !== lastUrl) {
            lastUrl = url;
            checkPageUrl(url);
        }
    }).observe(document, {subtree: true, childList: true});

    // 检查页面URL是否匹配监控列表
    function checkPageUrl(url) {
        if (window.monitoredUrls.some(monitoredUrl => url.includes(monitoredUrl))) {
            console.log(`页面导航到目标URL: ${url}`);
            console.log(`匹配的路径: ${window.monitoredUrls.find(monitoredUrl => url.includes(monitoredUrl))}`);

            // 这里可以添加修改页面内容的代码
            // 目前先用log示例
            console.log('检测到目标页面，可以在这里修改页面内容');
            
            // 添加上传按钮
            addUploadButton();

            // 添加自定义事件，通知其他脚本
            const event = new CustomEvent('MonitoredPageLoaded', {
                detail: {
                    url: url,
                    matchedPath: window.monitoredUrls.find(monitoredUrl => url.includes(monitoredUrl))
                }
            });
            document.dispatchEvent(event);
        }
    }

    // 页面加载完成后显示提示信息
    window.addEventListener('load', function() {
        console.log('MS.ZJER.CN 参数拦截与URL侦听脚本已加载成功！');

        // 检查当前页面URL
        checkPageUrl(window.location.href);

        if (Object.keys(window.interceptedParams).length > 0) {
            console.log('已成功拦截请求参数，可使用以下全局变量:');
            console.log('window.ukey, window.is_admin, window.csrftk');
        } else {
            console.log('尚未拦截到目标请求，等待请求发生...');
        }

        console.log('监控的URL路径:', window.monitoredUrls);
    });

    // 提供一个函数来检查全局变量状态
    window.checkInterceptedParams = function() {
        console.log('当前全局变量状态:');
        console.log(`ukey: ${window.ukey}`);
        console.log(`is_admin: ${window.is_admin}`);
        console.log(`csrftk: ${window.csrftk}`);
        return {
            ukey: window.ukey,
            is_admin: window.is_admin,
            csrftk: window.csrftk
        };
    };

    // 提供一个函数来检查当前页面是否匹配监控URL
    window.checkCurrentPage = function() {
        const currentUrl = window.location.href;
        const matchedPath = window.monitoredUrls.find(monitoredUrl => currentUrl.includes(monitoredUrl));

        if (matchedPath) {
            console.log(`当前页面匹配监控路径: ${matchedPath}`);
            return matchedPath;
        } else {
            console.log('当前页面不匹配任何监控路径');
            return null;
        }
    };
    
    // 检查当前URL是否匹配目标URL
    function isTargetPage() {
        const currentUrl = window.location.href;
        // 检查是否匹配监控URL列表中的任意一个
        return window.monitoredUrls.some(urlPattern => currentUrl.includes(urlPattern));
    }
    
    // 定义执行函数
    function init() {
        console.log('脚本初始化完成');
        
        // 初始化参数拦截
        initParamsInterceptor();
        
        // 添加上传按钮
        addUploadButton();
        
        // 监听DOM变化，处理动态加载的内容
        observeDOM();
    }
    
    // 监听动态加载事件
    function listenForDynamicLoad() {
        // 监听自定义的动态加载完成事件
        document.addEventListener('dynamicContentLoaded', function() {
            console.log('检测到动态内容加载完成事件');
            checkAndExecute();
        });
        
        // 监听可能的页面更新事件
        document.addEventListener('pageUpdated', function() {
            console.log('检测到页面更新事件');
            checkAndExecute();
        });
        
        // 使用MutationObserver监听DOM变化
        const observer = new MutationObserver(function(mutations) {
            // 检查是否有重大DOM变化
            let significantChange = false;
            mutations.forEach(function(mutation) {
                if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                    mutation.addedNodes.forEach(function(node) {
                        if (node.nodeType === 1) { // 元素节点
                            // 检查是否添加了页面主要内容元素
                            if (node.id || node.className) {
                                significantChange = true;
                            }
                        }
                    });
                }
            });
            
            if (significantChange) {
                console.log('检测到重大DOM变化');
                setTimeout(checkAndExecute, 100); // 延迟执行以确保DOM更新完成
            }
        });
        
        // 配置观察选项
        const config = {
            childList: true,
            subtree: true
        };
        
        // 开始观察
        observer.observe(document.body, config);
        
        // 同时监听History API变化
        const originalPushState = history.pushState;
        const originalReplaceState = history.replaceState;
        
        history.pushState = function() {
            const result = originalPushState.apply(this, arguments);
            setTimeout(() => {
                console.log('检测到pushState导航');
                checkAndExecute();
            }, 100);
            return result;
        };
        
        history.replaceState = function() {
            const result = originalReplaceState.apply(this, arguments);
            setTimeout(() => {
                console.log('检测到replaceState导航');
                checkAndExecute();
            }, 100);
            return result;
        };
        
        // 监听popstate事件
        window.addEventListener('popstate', () => {
            setTimeout(() => {
                console.log('检测到popstate导航');
                checkAndExecute();
            }, 100);
        });
        
        // 初始检查一次
        setTimeout(checkAndExecute, 1000);
    }
    
    // 检查并执行功能
    function checkAndExecute() {
        if (isTargetPage()) {
            console.log('当前为目标页面，执行功能');
            observeDOM(); // 继续监听DOM变化以处理编辑器相关元素
        } else {
            console.log('当前非目标页面，跳过执行');
        }
    }
    
    //定义参数，用于图片上传
    const params = {
        ukey: '',
        is_admin: '',
        csrftk: '',
        noCache: ''
    };

    // 初始化参数拦截器
    function initParamsInterceptor() {
        // 存储拦截到的参数
        window.interceptedParams = {};
        
        // 保存原始XMLHttpRequest
        const originalOpen = XMLHttpRequest.prototype.open;
        const originalSend = XMLHttpRequest.prototype.send;
        
        // 重写XMLHttpRequest的open方法
        XMLHttpRequest.prototype.open = function() {
            const url = arguments[1];
            
            // 检查是否为目标URL
            if (url && url.includes('common/ueditor/index/index')) {
                console.log('拦截到目标请求:', url);
                
                // 解析URL参数
                const urlObj = new URL(url, window.location.origin);
                const urlParams = Object.fromEntries(urlObj.searchParams.entries());
                
                // 提取并存储指定参数为全局变量
                params.ukey = urlParams.ukey || '';
                params.is_admin = urlParams.is_admin || '';
                params.csrftk = urlParams.csrftk || '';
                params.noCache = urlParams.noCache || '';
                
                // 设置全局变量供其他功能使用
                window.ukey = params.ukey;
                window.is_admin = params.is_admin;
                window.csrftk = params.csrftk;
                window.noCache = params.noCache;
            }
            
            // 调用原始open方法
            return originalOpen.apply(this, arguments);
        };
        
        // 重写send方法以保持一致性
        XMLHttpRequest.prototype.send = function() {
            return originalSend.apply(this, arguments);
        };
        
        // 页面加载完成后显示提示信息
        window.addEventListener('load', function() {
            console.log('MS.ZJER.CN 参数拦截脚本已加载成功！');
            if (Object.keys(window.interceptedParams).length > 0) {
                console.log('已获取请求参数');
            } else {
                console.log('尚未获取必要参数...');
            }
        });
    }
    
    // 获取拦截到的参数
    function getInterceptedParams() {
        return window.interceptedParams || {};
    }
    
    // 添加上传按钮的函数
    function addUploadButton() {
        // 等待一段时间确保编辑器加载完成
        setTimeout(function() {
            // 查找工具栏容器 - 增强检测逻辑
            let toolbar = document.querySelector('.edui-toolbar');
            
            // 如果没找到，尝试其他可能的选择器
            if (!toolbar) {
                toolbar = document.querySelector('[id*="edui"] .edui-toolbar');
            }
            
            if (!toolbar) {
                toolbar = document.querySelector('[class*="edui"] .edui-toolbar');
            }
            
            // 如果仍然没找到，尝试查找包含edui的元素
            if (!toolbar) {
                const eduiElements = document.querySelectorAll('[id*="edui"], [class*="edui"]');
                for (let element of eduiElements) {
                    if (element.querySelector('.edui-toolbar')) {
                        toolbar = element.querySelector('.edui-toolbar');
                        break;
                    }
                }
            }
            
            if (toolbar) {
                // 检查按钮是否已经存在，防止重复添加
                if (document.querySelector('.ueditor-docx-upload-button')) {
                    console.log('上传按钮已存在，防止重复添加');
                    return;
                }
                
                // 创建上传按钮
                const uploadButton = document.createElement('div');
                uploadButton.className = 'edui-box edui-button edui-default ueditor-docx-upload-button';
                uploadButton.style.cssText = 'margin-left: 5px; cursor: pointer;';
                uploadButton.title = '上传DOCX文档';
                
                // 创建按钮内容
                uploadButton.innerHTML = `
                    <div class="edui-button-wrap edui-default">
                        <div class="edui-button-body edui-default" style="padding: 0 5px;">
                            <span style="display: flex; align-items: center; font-size: 12px;">
                                📄 上传DOCX
                            </span>
                        </div>
                    </div>
                `;
                
                // 添加点击事件
                uploadButton.addEventListener('click', function() {
                    console.log('点击了上传DOCX按钮');
                    openFileUploadDialog();
                });
                
                // 将按钮添加到工具栏末尾
                toolbar.appendChild(uploadButton);
                console.log('已添加上传DOCX按钮');
            } else {
                console.log('未找到编辑器工具栏，将在1秒后重试');
                // 如果没找到工具栏，稍后重试
                setTimeout(addUploadButton, 1000);
            }
        }, 1000); // 等待1秒确保编辑器加载完成
    }
    
    // 打开文件上传对话框
    function openFileUploadDialog() {
        // 创建隐藏的文件输入元素
        const fileInput = document.createElement('input');
        fileInput.type = 'file';
        fileInput.accept = '.docx'; // 限制只能选择docx文件
        fileInput.style.display = 'none';
        
        // 添加文件选择事件监听器
        fileInput.addEventListener('change', function(event) {
            const file = event.target.files[0];
            if (file) {
                console.log('选择的文件:', file.name);
                console.log('文件类型:', file.type);
                console.log('文件大小:', file.size, 'bytes');
                
                // 解析DOCX文件
                parseDocxFile(file);
            }
        });
        
        // 将文件输入元素添加到页面并触发点击事件
        document.body.appendChild(fileInput);
        fileInput.click();
        
        // 文件选择完成后从页面中移除该元素
        fileInput.addEventListener('cancel', function() {
            document.body.removeChild(fileInput);
        });
        
        fileInput.addEventListener('change', function() {
            document.body.removeChild(fileInput);
        });
    }
    
    // 解析DOCX文件
    function parseDocxFile(file) {
        const reader = new FileReader();
        
        reader.onload = function(event) {
            const arrayBuffer = event.target.result;
            
            // 使用Mammoth.js解析DOCX文件，添加图片处理选项
            const options = {
                convertImage: mammoth.images.imgElement(function(image) {
                    return image.read("base64").then(function(base64Image) {
                        // 上传图片并返回新的img元素
                        return uploadImage(base64Image).then(function(url) {
                            return {
                                src: url
                            };
                        }).catch(function(error) {
                            console.error("图片上传失败:", error);
                            // 如果上传失败，仍然显示图片但使用base64数据
                            return {
                                src: "data:image/png;base64," + base64Image
                            };
                        });
                    });
                })
            };
            
            // 使用Mammoth.js解析DOCX文件
            mammoth.convertToHtml({arrayBuffer: arrayBuffer}, options)
                .then(function(result) {
                    const html = result.value; // 转换后的HTML内容
                    const messages = result.messages; // 解析过程中的任何消息
                    
                    // 显示解析结果
                    console.log('DOCX解析完成');
                    console.log('HTML内容:', html);
                    console.log('解析消息:', messages);
                    
                    // 统计段落、表格和图片数量
                    const counts = countDocxElements(html);
                    
                    // 将内容插入到编辑器
                    insertContentToEditor(html);
                })
                .catch(function(error) {
                    console.error('解析DOCX文件时出错:', error);
                });
        };
        
        reader.onerror = function(event) {
            console.error('读取文件时出错:', event.target.error);
        };
        
        // 读取文件为ArrayBuffer
        reader.readAsArrayBuffer(file);
    }
    
    // 统计DOCX文档中的元素数量
    function countDocxElements(html) {
        // 创建一个临时的div来解析HTML内容
        const tempDiv = document.createElement('div');
        tempDiv.innerHTML = html;
        
        // 统计段落数量
        const paragraphs = tempDiv.querySelectorAll('p');
        const paragraphCount = paragraphs.length;
        
        // 统计表格数量
        const tables = tempDiv.querySelectorAll('table');
        const tableCount = tables.length;
        
        // 统计图片数量
        const images = tempDiv.querySelectorAll('img');
        const imageCount = images.length;
        
        // 在控制台显示统计结果
        console.log('文档元素统计:');
        console.log('段落数量:', paragraphCount);
        console.log('表格数量:', tableCount);
        console.log('图片数量:', imageCount);
        
        // 返回统计结果
        return {
            paragraphs: paragraphCount,
            tables: tableCount,
            images: imageCount
        };
    }
    
    // 上传图片到服务器
    function uploadImage(base64Image) {
        return new Promise(function(resolve, reject) {
            // 检查必要的参数是否存在
            if (!window.ukey || !window.is_admin || !window.csrftk) {
                reject(new Error("缺少必要的上传参数"));
                return;
            }
            
            // 将base64转换为Blob
            const byteString = atob(base64Image.split(',')[1]);
            const mimeString = base64Image.split(',')[0].split(':')[1].split(';')[0];
            const ab = new ArrayBuffer(byteString.length);
            const ia = new Uint8Array(ab);
            for (let i = 0; i < byteString.length; i++) {
                ia[i] = byteString.charCodeAt(i);
            }
            const blob = new Blob([ab], {type: mimeString});
            
            // 读取blob为ArrayBuffer，然后转换为base64字符串用于GET参数
            const reader = new FileReader();
            reader.onload = function(event) {
                // 获取base64数据（去除data URL前缀）
                const base64Data = event.target.result.split(',')[1];
                
                // 构造上传URL，将图片数据作为参数
                const params = new URLSearchParams();
                params.append('ukey', window.ukey);
                params.append('is_admin', window.is_admin);
                params.append('csrftk', window.csrftk);
                params.append('action', 'uploadimage');
                params.append('encode', 'utf-8');
                params.append('imageData', base64Data); // 将图片数据作为参数传递
                
                const uploadUrl = `https://ms.zjer.cn/index.php?r=common/ueditor/index/index&${params.toString()}`;
                
                // 使用GM_xmlhttpRequest发送GET请求
                GM_xmlhttpRequest({
                    method: 'GET',
                    url: uploadUrl,
                    onload: function(response) {
                        try {
                            const result = JSON.parse(response.responseText);
                            if (result.state === 'SUCCESS') {
                                console.log('图片上传成功:', result.url);
                                resolve(result.url);
                            } else {
                                console.error('图片上传失败:', result);
                                reject(new Error(result.state || '上传失败'));
                            }
                        } catch (e) {
                            console.error('解析上传响应失败:', e);
                            reject(e);
                        }
                    },
                    onerror: function(error) {
                        console.error('图片上传出错:', error);
                        reject(error);
                    }
                });
            };
            
            // 读取blob为data URL
            reader.readAsDataURL(blob);
        });
    }
    
    // 将内容插入到UEditor中
    function insertContentToEditor(html) {
        try {
            // 根据页面代码，编辑器实例可能是window.UE.instants['ueditorInstant0']
            let editor = null;
            
            // 尝试多种方式获取编辑器实例
            if (window.UE && window.UE.instants && window.UE.instants['ueditorInstant0']) {
                editor = window.UE.instants['ueditorInstant0'];
            } else if (window.UE && window.UE.getEditor) {
                // 获取所有编辑器实例
                const editorIds = Object.keys(UE.instances);
                if (editorIds.length > 0) {
                    editor = UE.getEditor(editorIds[0]);
                }
            }
            
            if (editor) {
                // 确保编辑器已经准备就绪
                if (editor.isReady) {
                    editor.execCommand('insertHtml', html);
                    console.log('内容已插入编辑器');
                } else {
                    // 等待编辑器准备就绪
                    editor.ready(function() {
                        editor.execCommand('insertHtml', html);
                        console.log('内容已插入编辑器');
                    });
                }
            } else {
                // 如果无法获取编辑器实例，尝试直接操作iframe
                const iframe = document.getElementById('ueditor_0');
                if (iframe) {
                    const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
                    const body = iframeDoc.querySelector('body.view');
                    if (body) {
                        body.innerHTML += html;
                        console.log('内容已插入iframe');
                    } else {
                        console.log('未找到编辑器body');
                    }
                } else {
                    console.log('未找到编辑器iframe');
                }
            }
        } catch (error) {
            console.error('插入内容到编辑器时出错:', error);
        }
    }
    
    // 启动DOM观察器
    function observeDOM() {
        // 创建一个MutationObserver实例
        const observer = new MutationObserver(function(mutations) {
            mutations.forEach(function(mutation) {
                // 检查是否有新增节点
                if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                    // 检查是否添加了UEditor相关元素
                    mutation.addedNodes.forEach(function(node) {
                        // 确保节点是元素节点
                        if (node.nodeType === 1) {
                            // 检查是否包含UEditor工具栏或相关元素
                            if (node.querySelector &&
                                (node.querySelector('.edui-toolbar') ||
                                 node.querySelector('[id*="edui"]') ||
                                 node.querySelector('[class*="edui"]') ||
                                 node.id === 'ueditor_0')) {
                                console.log('检测到UEditor元素动态加载');
                                // 延迟执行以确保元素完全加载
                                setTimeout(addUploadButton, 100);
                            }
                        }
                    });
                }
            });
        });

        // 配置观察选项
        const config = {
            childList: true,
            subtree: true
        };

        // 开始观察
        observer.observe(document.body, config);

        // 在页面卸载时断开观察器连接
        window.addEventListener('beforeunload', function() {
            observer.disconnect();
        });
    }

    // 检查当前页面是否为目标页面
    // 注意：即使当前不是目标页面，也要初始化脚本以监听URL变化
    console.log('脚本开始执行，检查页面状态');
    console.log('当前页面URL:', window.location.href);
    console.log('是否为目标页面:', isTargetPage());

    // 检查DOM是否已经加载完成
    if (document.readyState === 'loading') {
        // DOM仍在加载中，等待DOMContentLoaded事件
        document.addEventListener('DOMContentLoaded', init);
    } else {
        // DOM已经加载完成，直接执行
        init();
    }
})();